#include "LecteurSymbole.h"
#include <ctype.h>
#include <string.h>
#include <iostream>
#include <cstdlib>
using namespace std;

////////////////////////////////////////////////////////////////////////////////

LecteurSymbole::LecteurSymbole(string nomFich) :
lc(nomFich), symCour("") {
    suivant(); // pour lire le premier symbole
}

////////////////////////////////////////////////////////////////////////////////

void LecteurSymbole::suivant() {
    while (sauterCommentaire() || sauterSeparateurs());
    // on est maintenant positionne sur le premier caractère d'un symbole
    ligne = lc.getLigne();
    colonne = lc.getColonne();
    symCour = Symbole(motSuivant()); // on reconstruit symCour avec le nouveau mot lu
}

////////////////////////////////////////////////////////////////////////////////

bool LecteurSymbole::sauterSeparateurs() {
    bool onAPasseUnSeparateur = false;
    while (lc.getCarCour() == ' ' ||
            lc.getCarCour() == '\t' ||
            lc.getCarCour() == '\r' ||
            lc.getCarCour() == '\n') {
        lc.suivant();
        onAPasseUnSeparateur = true;
    }
    return onAPasseUnSeparateur;

}

////////////////////////////////////////////////////////////////////////////////

bool LecteurSymbole::sauterCommentaire() {
    bool onAPasseUnCommentaire = false;
    while (lc.getCarCour() == '#') {
        onAPasseUnCommentaire = true;
        while (lc.getCarCour() != '\n' && lc.getCarCour() != EOF) {
            //On s'arrête à un retour à la ligne
            lc.suivant();
        }
        if (lc.getCarCour() == '\n') {
            //On passe au caractère suivant le retour à la ligne
            lc.suivant();
        }

    }
    return onAPasseUnCommentaire;
}

////////////////////////////////////////////////////////////////////////////////

string LecteurSymbole::motSuivant() {
    static string s;
    s = "";
    if (isdigit(lc.getCarCour())) {
        // c'est le début d'une valeur numérique (entier/réel)
        do {
            s = s + lc.getCarCour();
            lc.suivant();
        } while (isdigit(lc.getCarCour()) || lc.getCarCour() == '.');

    } else if (lc.getCarCour() == '"')
        // c'est le début d'une chaine
    {
        do {
            s = s + lc.getCarCour();
            lc.suivant();
        } while (lc.getCarCour() != '"' && lc.getCarCour() != EOF);
        if (lc.getCarCour() == EOF) // Fin de fichier non attendu
        {
            cout << "Erreur : Chaine pas fermée ligne " << this->ligne << " caractère " << this->colonne << endl;
            exit(0); // Exception à faire
        } else {
            s = s + '"';
            lc.suivant();
        }
    } else if (lc.getCarCour() == '\'')
        // c'est un caractère
    {
        do {
            s = s + lc.getCarCour();
            lc.suivant();
        } while (lc.getCarCour() != '\'' && lc.getCarCour() != EOF);
        if (lc.getCarCour() == EOF) // Fin de fichier non attendu
        {
            cout << "Erreur : Caractère \" \' \" attendu ligne " << this->ligne << " caractère " << this->colonne << endl;
            exit(0); // Exception à faire
        } else if (s.length() > 3 || (s.length() == 3 && s[1] != '\\')) {
            cout << "Erreur : Pas un caractère ligne " << this->ligne << " caractère " << this->colonne << endl;
            exit(0); // Exception à faire
        } else {
            s = s + '\'';
            lc.suivant();
        }
    } else if (isalpha(lc.getCarCour())) {
        // c'est le début d'un mot/variable
        do {
            s = s + lc.getCarCour();
            lc.suivant();
        } while (isalpha(lc.getCarCour()) ||
                isdigit(lc.getCarCour()) ||
                lc.getCarCour() == '_');

    } else if (lc.getCarCour() == '=' ||
            lc.getCarCour() == '!' ||
            lc.getCarCour() == '<' ||
            lc.getCarCour() == '>') {
        // c'est le début d'un mot (==,!=,<=,>=)
        do {
            s = s + lc.getCarCour();
            lc.suivant();
        } while (lc.getCarCour() == '=');

    } else if (lc.getCarCour() != EOF)
        // c'est un caractere special
    {
        s = s + lc.getCarCour();
        lc.suivant();
    }
    return s;
}
